package com.hwd.gmall.seckill.service.impl;

import com.hwd.gmall.common.constant.SeckillConst;
import com.hwd.gmall.model.activity.SeckillGoods;
import com.hwd.gmall.seckill.mapper.SeckillGoodsMapper;
import com.hwd.gmall.seckill.service.SeckillGoodsService;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 秒杀商品业务模块的接口实现类
 *
 * @author 黄伟东/Victor
 * @date 2022/5/11 18:21
 */
@Service
@Log4j2
public class SeckillGoodsServiceImpl implements SeckillGoodsService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private SeckillGoodsMapper seckillGoodsMapper;

    /**
     * 查询指定时间段的秒杀商品的列表
     *
     * @param startTime 指定时间段的开始时间
     * @return java.util.List<com.hwd.gmall.model.activity.SeckillGoods>
     */
    @Override
    public List<SeckillGoods> listSeckillGoods(String startTime) {
        return redisTemplate.opsForHash().values(startTime)
                .stream().map(SeckillGoods.class::cast)
                .collect(Collectors.toList());
    }

    /**
     * 查询指定的秒杀商品数据
     *
     * @param startTime 指定时间段的开始时间
     * @param goodsId   商品id
     * @return com.hwd.gmall.model.activity.SeckillGoods
     */
    @Override
    public SeckillGoods getSeckillGoods(String startTime, String goodsId) {
        return (SeckillGoods) redisTemplate.opsForHash().get(startTime, goodsId);
    }

    /**
     * 将秒杀商品的数据从redis中进行同步到去数据库中
     *
     * @param time 时间段
     */
    @Override
    public void mergeSeckillGoodsStockFromRedisToDb(String time) {

        // 获取秒杀商品库存自增值在redis中的key
        String goodsStockKey = SeckillConst.SECKILL_GOODS_STOCK + time;

        // 获取这个时间段的所有商品的id
        Set<Object> goodsIds = redisTemplate.opsForHash().keys(goodsStockKey);
        goodsIds.forEach(item -> {
            // 获取每个商品的id
            String goodsId = (String) item;
            // 获取这个商品剩余的库存
            Integer stockNum = (Integer) redisTemplate.opsForHash().get(goodsStockKey, goodsId);
            // 修改
            int updateStock = seckillGoodsMapper.updateStock(Long.parseLong(goodsId), stockNum);
            if (updateStock < 0) {
                //选择记录日志,也可以选择记录数据库中
                log.error("秒杀商品数据同步的时候,出现同步失败,同步失败的商品所属的时间段为: " + time);
                log.error("秒杀商品数据同步的时候,出现同步失败,同步失败的商品id为: " + goodsId);
                log.error("秒杀商品数据同步的时候,出现同步失败,同步失败的商品的剩余库存为 : " + stockNum);
            }
        });

        // 所有商品的数据都同步成功,清理这个库存的key
        redisTemplate.delete(goodsStockKey);
    }
}
